﻿//========================================================= 
/**@file zabbix_converter.h
 * @brief Zabbix转换插件模块
 * 
 * @date 2018-10-14   14:38:56
 * @author Zhyioo 
 * @version 1.0
 */ 
//--------------------------------------------------------- 
#ifndef _LIBZHOUYB_ZABBIX_CONVERTER_H_
#define _LIBZHOUYB_ZABBIX_CONVERTER_H_
//--------------------------------------------------------- 
#include "../../include/Base.h"

#include "../../application/tools/WinConverterLoader.h"
using zhou_yb::application::tools::ConverterInvoker;
using zhou_yb::application::tools::WinConverterLoader;

#include "../../extension/ability/ThreadTask.h"
using zhou_yb::extension::ability::ThreadTask;
//--------------------------------------------------------- 
namespace zhou_yb {
namespace wrapper {
namespace zabbix_extractor {
//--------------------------------------------------------- 
/**
 * @brief Zabbix监控命令调度器
 * @date 2018-10-11 11:21:52
 */
class converter_invoker
{
protected:
    list_t<ConverterInvoker> _cvts;

    list_t<ConverterInvoker>::iterator get_command(const string& cmd)
    {
        list_t<ConverterInvoker>::iterator itr;
        for(itr = _cvts.begin(); itr != _cvts.end(); ++itr)
        {
            if(itr->Title == cmd)
                return itr;
        }
        return _cvts.end();
    }
public:
    converter_invoker() {}
    converter_invoker(const char* dir) { load(dir); }

    size_t load(const char* dir = ".\\")
    {
        return WinConverterLoader::LoadFromFolder(dir, _cvts);
    }
    size_t get(list_t<string>& cmds) const
    {
        list_t<ConverterInvoker>::const_iterator itr;
        for(itr = _cvts.begin(); itr != _cvts.end(); ++itr)
        {
            cmds.push_back(itr->Title);
        }
        return _cvts.size();
    }
    int on_command(const string& cmd, const string& arg, string& rlt)
    {
        list_t<ConverterInvoker>::iterator itr = get_command(cmd);
        if(itr == _cvts.end())
            return DeviceError::ArgRangeErr;
        if(!(itr->Convert(arg.c_str(), rlt, NULL)))
            return DeviceError::OperatorErr;
        return DeviceError::Success;
    }
};
//--------------------------------------------------------- 
/**
 * @brief 单个转换任务队列
 * @date 2018-10-12 15:51:53
 */
class converter_async_worker : public ThreadTask<std::pair<string, 
    std::function<void(const string&,bool, const string&, const string&)> > >
{
public:
    typedef std::function<void(const string&, bool, const string&, const string&)> callback_type;
protected:
    virtual void OnTask(ParamType& param)
    {
        string rlt = "";
        bool bOK = Converter.Convert(param.first.c_str(), rlt, NULL);
        if(param.second != nullptr)
        {
            param.second(Converter.Title, bOK, param.first, rlt);
        }
    }
public:
    converter_async_worker() : ThreadTask<std::pair<string, callback_type> >() {}

    ConverterInvoker Converter;
    /**
     * @brief 添加任务
     * @date 2018-10-12 11:11:24
     */
    void Push(const string& param, callback_type callback)
    {
        std::pair<string, callback_type> node(param, callback);
        ThreadTask<std::pair<string, callback_type> >::Push(node);
    }
};
//--------------------------------------------------------- 
/**
 * @brief 多个转换任务的调度器
 * @date 2018-10-29 22:06:55
 */
class converter_dispatcher : public converter_invoker
{
public:
    typedef converter_async_worker::callback_type callback_type;
protected:
    MapArguments<string, converter_async_worker*> _pool;
    list_t<converter_async_worker> _objs;
    std::mutex _mutex;

    bool _async(const string& cmd, const string& arg, callback_type callback)
    {
        list_t<ConverterInvoker>::iterator itr = get_command(cmd);
        if(itr == _cvts.end()) return false;
        converter_async_worker* pWorker = NULL;
        if(!_pool.Contains(cmd))
        {
            pWorker = &(*_objs.push_back());
            pWorker->Converter = (*itr);
            _pool.Put(cmd, pWorker);
        }
        else
        {
            pWorker = _pool.Get(cmd);
        }
        pWorker->Push(arg, callback);
        return true;
    }
public:
    converter_dispatcher() : converter_invoker() {}
    converter_dispatcher(const char* dir) : converter_invoker(dir) {}
    virtual ~converter_dispatcher() { stop(); }

    int async(const string& cmd, const string& arg, callback_type callback)
    {
        if(!_mutex.try_lock()) return DeviceError::DevIsBusyErr;
        bool bOK = _async(cmd, arg, callback);
        _mutex.unlock();
        return bOK ? DeviceError::Success : DeviceError::ArgRangeErr;
    }
    void stop()
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _pool.Clear();

        list_t<converter_async_worker>::iterator itr;
        for(itr = _objs.begin();itr != _objs.end(); ++itr)
        {
            itr->Quit();
        }
        _objs.clear();
    }
};
//--------------------------------------------------------- 
} // namespace zabbix_extractor 
} // namespace wrapper
} // namespace zhou_yb 
//--------------------------------------------------------- 
#endif // _LIBZHOUYB_ZABBIX_CONVERTER_H_
//========================================================= 